package freedom.needle.task.impl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import freedom.needle.enums.TaskCommand;
import freedom.needle.sleep.SleepStrategy;
import freedom.needle.task.Task;

public abstract class AbstractCycleTask implements Task {
	
	protected final Logger logger = LoggerFactory.getLogger(getClazz());
	protected int workers;
	protected SleepStrategy sleepStrategy; 
	private volatile TaskCommand command = TaskCommand.INIT;

	public abstract Class<?> getClazz();

	@Override
	public abstract void execute() throws Exception;

	@Override
	public void run() {
			while(true) {
				if(command == TaskCommand.RUN) {
					try {
						execute();
					} catch (Exception e) {
						//主动中断，忽略
						if(isInterruptedExceptionCause(e))
							logger.warn("execute() is interrupted");
						else 
							logger.error("execute() fail!", e);
					}
				} else if(command == TaskCommand.STOP) {
					break;
				} else {
					sleepStrategy.increase();
				}
				
				try {
					if(sleepStrategy.getTime() != 0)
						Thread.sleep(sleepStrategy.getTime());
				} catch (InterruptedException e) {
					logger.warn("sleep is interrupted");
				}
			}
	}


	/**
	 * 判定是否是中断异常
	 * @param t
	 * @return
	 */
	private boolean isInterruptedExceptionCause(Throwable t) {
		while(true) {
			if(t == null)
				return false;
			else if(t instanceof InterruptedException)
				return true;
			else 
				t = t.getCause();
		}
	}
	
	
	/**
	 * @return the sleepStrategy
	 */
	public SleepStrategy getSleepStrategy() {
		return sleepStrategy;
	}

	/**
	 * @param sleepStrategy the sleepStrategy to set
	 */
	public void setSleepStrategy(SleepStrategy sleepStrategy) {
		this.sleepStrategy = sleepStrategy;
	}

	/**
	 * @return the command
	 */
	public TaskCommand getCommand() {
		return command;
	}

	/**
	 * @param command the command to set
	 */
	public void setCommand(TaskCommand command) {
		this.command = command;
	}

	/**
	 * @return the workers
	 */
	public int getWorkers() {
		return workers;
	}

	/**
	 * @param workers the workers to set
	 */
	public void setWorkers(int workers) {
		this.workers = workers;
	}
	
}
